package com.czapl.drawing;

import java.util.List;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.actions.AlphaAction;
import com.badlogic.gdx.scenes.scene2d.actions.RemoveActorAction;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.czapl.api.IUnit;
import com.czapl.mygdxgame.CellCoordinates;
import com.czapl.mygdxgame.GameBoard;
import com.czapl.mygdxgame.MainScreen;

public abstract class CUnit extends Actor implements IUnit {

	public static final boolean UNIT_KILLED = true;
	public static final boolean TARGET_REACHED = false;
	
	protected float m_speed = 0;
	protected float m_maxHp = 100;
	protected float m_currentHp = 100;
	protected float m_damageModifier = 1;
	protected float m_radius = 16;
	protected String m_name = "Unit";
	protected AnimatedSprite m_sprite;
	
	private ConditionBar m_conditionBar;
	private float m_distanceTravelled = 0;
	
	private float m_size = GameBoard.TILE_SIZE;
	private boolean m_disposed = false;
	private Vector2 m_position = new Vector2();

	private IUnitTargetReachedListener m_targetReachedListener;
	private IUnitSelectionListener m_selectionListener;
	private IUnitStatusChangedListener m_statusChangedListener;
	
	private float m_spriteRotation = 0;
	
	public CUnit() {
		m_conditionBar = new ConditionBar(m_maxHp);
		setSize(m_size, m_size);
		m_conditionBar.setSize(m_size, m_size);
		
		addListener( new ClickListener() {
            @Override
            public void clicked(InputEvent event,float x,float y ) {
            	m_selectionListener.onUnitSelected(CUnit.this);
            }
        } );
		
	}

	@Override
	public void draw (SpriteBatch batch, float parentAlpha) {
        Color color = getColor();
        batch.setProjectionMatrix(getStage().getCamera().combined);
        batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
        batch.draw(m_sprite, getX(), getY(), getOriginX()+getWidth()/2, getOriginY()+getHeight()/2,
                getWidth(), getHeight(), getScaleX(), getScaleY(), m_spriteRotation);
	}

	@Override
	public void act (float delta) {
		super.act(delta);
		if(!m_disposed) {
			m_distanceTravelled += m_speed;
			m_sprite.update(delta);
			m_position.x = getX()+getWidth()/2;
			m_position.y = getY()+getHeight()/2;
			Vector2 coordinates = distanceToCoordinates(m_distanceTravelled );
			setX(coordinates.x);
			setY(coordinates.y);
		}
	}
	
	@Override
	public float getSpeed() {
		return m_speed;
	}

	@Override
	public void setSpeed(float m_speed) {
		this.m_speed = m_speed;
		m_sprite.setAnimationRate((int) (m_speed*10));
		m_sprite.play();
	}

	@Override
	public void dispose(boolean killed) {
		AlphaAction alphaAction = new AlphaAction();
		alphaAction.setAlpha(0);
		alphaAction.setDuration(0.3f);
		RemoveActorAction removeActorAction = new RemoveActorAction();
    	addAction(Actions.sequence(alphaAction,removeActorAction));
    	m_disposed = true;
    	if(MainScreen.getGameBoard().getUnits().removeValue(this, true)) {
			System.out.println("removed from list");
		}
	}

	@Override
	public void drawConditionBar() {
		if(!m_disposed) {
		m_conditionBar.draw(getStage().getCamera().combined, getX(), getY());
		}
	}

	@Override
	public Vector2 getPosition() {
		return m_position.cpy();
	}

	@Override
	public void setUnitSelectionListener(IUnitSelectionListener listener) {
		m_selectionListener = listener;
		
	}

	@Override
	public void setUnitStatusChangedListener(IUnitStatusChangedListener listener) {
		m_statusChangedListener = listener;
	}
	
	@Override
	public void damage(float damageBase) {
		m_currentHp -= damageBase*m_damageModifier;
		if(m_currentHp <= 0) {
			dispose(UNIT_KILLED);
		}
		m_conditionBar.setHp(m_currentHp);
		if(m_statusChangedListener != null) {
			m_statusChangedListener.onUnitStatusChanged(this);
		}
	}

	@Override
	public void setCellChangeListener(IUnitTargetReachedListener listener) {
		m_targetReachedListener = listener;
		
	}
	
	private Vector2 distanceToCoordinates(float distance) {
		List<CellCoordinates> path = MainScreen.getGameBoard().getPath();
		int idx = (int) (distance/m_size);
		float deltaX = 0, deltaY = 0;
		//System.out.println("cell: "+idx);
		CellCoordinates newCell = path.get(idx);
		if(idx == path.size()-1) {
			m_targetReachedListener.onTargetReached(this);
			dispose(TARGET_REACHED);
			return new Vector2(newCell.getX()*m_size, newCell.getY()*m_size);
		}
		CellCoordinates nextCell = path.get(idx+1);
		
		if(newCell.getX() != nextCell.getX()) {
			if(newCell.getX() < nextCell.getX()) {
				deltaX = distance%m_size;
				m_spriteRotation = 0;
			}
			else {
				deltaX = -distance%m_size;
				m_spriteRotation = 180;
			}
		}
		else if(newCell.getY() != nextCell.getY()) {
			if(newCell.getY() < nextCell.getY()) {
				deltaY = distance%m_size;
				m_spriteRotation = 90;
			}
			else {
				deltaY = -distance%m_size;
				m_spriteRotation = 270;
			}
		}
		
		return new Vector2(newCell.getX()*m_size+deltaX, newCell.getY()*m_size+deltaY);
	}

	@Override
	public float getRadius() {
		return m_radius ;
	}

	@Override
	public AnimatedSprite getAnimatedSprite() {
		return m_sprite;
	}

	@Override
	public String getName() {
		return m_name;
	}
	
	@Override
	public float getCurrentHp() {
		return m_currentHp;
	}
	
	@Override
	public float getMaxHp() {
		return m_maxHp;
	}
	
}
